const defaultTagRE = /\{\{((?:.|\r?\n)+?)\}\}/g; // 匹配 {{}}

function generateChid(node) {
  if (node.type === 1) {  // 标签节点
    return generate(node); // 递归
  } else if (node.type === 3) { // 文本节点
    const text = node.text; // hello {{name}} yellow{{age}}
    // 匹配都没有 {{}}
    if (!defaultTagRE.test(text)) {
      return `_v(${JSON.stringify(text)})`;
    }
    // 可能只有 {{}} , 或者混合有 {{}}
    let match, index;
    const textArr = []; // 源码叫 tokens
    let lastIndex = defaultTagRE.lastIndex = 0; // 大坑，循环匹配需要处理，正则的lastIndex, 每次循环都需要修正，从 0 开始。
    // 匹配 {{}} 数据文本
    while (match = defaultTagRE.exec(text)) {
      index = match.index; // 匹配到当前文本的索引

      // 直接是字符串不是 {{}}
      if (index > lastIndex) { // 先匹配到 {{}} 前的文本，先放入 textArr 中
        textArr.push(JSON.stringify(text.slice(lastIndex, index)))
      }
      textArr.push(`_s(${match[1].trim()})`);
      lastIndex = index + match[0].length; // 不断往后匹配
    }

    // 直接是字符串不是 {{}}
    if (lastIndex < text.length) {
      textArr.push(JSON.stringify(text.slice(lastIndex))); // 字符串需要转换
    }
    const str = textArr.join('+'); // 把存储在数组中的 token 拼接成字符串
    return `_v(${str})`
  }
}

/**
 * 递归处理子元素
 * 
 * @param {*} ast AST 对象 
 */
function generateChidren(ast) {
  const children = ast.children;
  return children.map((child) => generateChid(child)).join(",");
}

/**
 * 生成属性的字符串
 * @param {*} attrs 标签属性对象
 * @returns
 */
function generateProps(attrs) {
  // 还没有处理驼峰的属性，如：fontSize, borderTop ...
  let attrStr = "";
  attrs.forEach((attr) => {
    if (attr.name === "style") {
      const styleAttrs = {};

      // attr.value.split(";").forEach((styleAttr) => {
      //     const [key, value] = styleAttr.split(":");
      //     styleAttrs[key.trim()] = value.trim();
      // });
      // 或者这种写法
      attr.value.split(';').reduce((memo, current) => {
        const [key, value] = current.split(':');
        memo[key.trim()] = value.trim();
        return memo;
      }, styleAttrs);

      attr.value = styleAttrs;
    }
    attrStr += `${attr.name}:${JSON.stringify(attr.value)},`;
  });
  const str = attrStr.slice(0, -1); // 去掉最后一个逗号
  // console.log('属性字符串：', str);
  return `{${str}}`;
}

/**
 * 将AST语法树对象，拼接成字符串代码
 * @param {*} ast
 */
export function generate(ast) {
  const el = ast;
  const children = generateChidren(el);
  const code = `_c("${el.tag}",${el.attrs.length ? `${generateProps(el.attrs)}` : "undefined"
    }${children ? `,${children}` : ""})`;
  // console.log("生成符合虚拟DOM结构的字符串：", code);
  // 最后生成这样的字符串代码：_c("div", { id: "app", disabled: true, style: { "color": "red", "background": "blue" } }, _v(_s(name)), _c("span", undefined, _v("helloworld"), _c("i", undefined, _v("ddd")), _c("p", undefined)))
  return code;
}
